home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / printing / print multipage pict / print.p < prev   
Encoding:
Text File  |  2000-09-28  |  10.6 KB  |  332 lines

  1. {
  2.     File:        print.p
  3.  
  4.     Contains:    Print multipage PICT:  Takes a PICT larger than one page and "tiles" it so that
  5.                 it prints across the right number of sheets of paper to tape together and make
  6.                 a poster, like many drawing applications.  You can find a slightly cleaner
  7.                 version of this routine as part of Pascal Sample 3.0.
  8.  
  9.     Written by:     
  10.  
  11.     Copyright:    Copyright © 1984-1999 by Apple Computer, Inc., All Rights Reserved.
  12.  
  13.                 You may incorporate this Apple sample source code into your program(s) without
  14.                 restriction. This Apple sample source code has been provided "AS IS" and the
  15.                 responsibility for its operation is yours. You are not permitted to redistribute
  16.                 this Apple sample source code as "Apple sample source code" after having made
  17.                 changes. If you're going to re-distribute the source, we require that you make
  18.                 it clear in the source that the code was descended from Apple sample source
  19.                 code, but that you've made changes.
  20.  
  21.     Change History (most recent first):
  22.                 7/26/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  23.                 
  24.  
  25. }
  26. {    This file has been processed by The THINK Pascal Source Converter, v1.1.2.    }
  27.  
  28. {    This file has been processed by The THINK Pascal Source Converter, v1.1.2.    }
  29. unit print;                                     { printing unit based on Luke's caring print loop }
  30.  
  31. interface
  32. uses
  33.     Printing,Resources,ToolUtils;
  34.  
  35. function Print (thePrRecHdl: THPrint): boolean;
  36. function PageSetup (thePrRecHdl: THPrint): boolean;
  37.  
  38. implementation
  39.  
  40. type
  41.  
  42.     heightAndWidth = record
  43.             height: integer;
  44.             width: integer;
  45.         end;
  46. var
  47.     theStatus: TPrStatus;
  48.     pageDims: heightAndWidth;
  49.     documentPicture: PicHandle;
  50.  
  51.  
  52. procedure AlertUser (rTheAlert: integer);
  53. EXTERNAL;
  54.  
  55. function GetPages (theDocBounds: Rect; thePrintRecord: THPrint): heightAndWidth;
  56.     var
  57.         pageLength, docLength, height, width: integer;
  58.  
  59. { Note that we'll use these "length" variables twice -- once for the width, and once for the height. }
  60. { They're just one-dimensional, so why use stack space to declare two copies? }
  61.  
  62.     begin
  63.         with theDocBounds do
  64.             docLength := right - left;
  65.         with thePrintRecord^^.prInfo.rPage do
  66.             pageLength := right - left;
  67.  
  68.         width := docLength div pageLength;
  69.         if docLength mod pageLength <> 0 then
  70.             width := width + 1;
  71.  
  72.         with theDocBounds do
  73.             docLength := bottom - top;
  74.         with thePrintRecord^^.prInfo.rPage do
  75.             pageLength := bottom - top;
  76.  
  77.         height := docLength div pageLength;
  78.         if docLength mod pageLength <> 0 then
  79.             height := height + 1;
  80.  
  81.         GetPages.width := width;
  82.         GetPages.height := height;
  83.  
  84.     end;
  85.  
  86. procedure UnLoadTheWorld;  {Nothing here right now for segmentation}
  87.  
  88. {    UnLoadTheWorld will swap out ALL unneeded code segments and data that are NOT required during print time.}
  89. {Your print code must be a separate code segment.  }
  90.  
  91.     begin
  92.     end;
  93.  
  94. function DetermineRealNumberOfPagesInDoc (documentSize: Rect; printRecord: THPrint): integer;
  95.  
  96.     begin
  97.         pageDims := GetPages(documentSize, printRecord);
  98.         DetermineRealNumberOfPagesInDoc := pageDims.height * pageDims.width;
  99.         ;
  100.     end;
  101.  
  102.  
  103. procedure DrawStuff (thePage: rect; thePort: GrafPtr; pageNumber: integer; thePicture: PicHandle);
  104.  
  105.     var
  106.         offsetPage: Rect;
  107.  
  108.     begin
  109.  
  110. { We draw pages horizontally first, then vertically, so if there are four pages, page 2 is to the right of page 1. }
  111.  
  112. { First, get the offset rectangle for the page we're drawing }
  113.  
  114.         offsetPage := thePicture^^.picFrame;
  115.         OffsetRect(offsetPage, -((pageNumber - 1) mod pageDims.width) * (thePage.right - thePage.left), -((pageNumber - 1) div pageDims.width) * (thePage.bottom - thePage.top));
  116.         DrawPicture(thePicture, offsetPage);
  117.  
  118.     end;
  119.  
  120. procedure MyPIdleProcedure;
  121.     var
  122.         pIdleEventRecord: EventRecord;
  123.     begin
  124.         if GetNextEvent(keyDownMask, pIdleEventRecord) then
  125.             begin
  126.                 if ((BitAnd(pIdleEventRecord.message, charCodeMask) = longint('.')) and (BitAnd(longint(pIdleEventRecord.modifiers), cmdKey) = cmdKey)) then
  127.                     PrSetError(iPrAbort);
  128.             end;
  129.     end;
  130.  
  131.  
  132. function PageSetup (thePrRecHdl: THPrint): boolean;
  133.  
  134.     var
  135.         PrintError: LongInt;
  136.         oldPort: GrafPtr;
  137.         printmgrsResFile: integer;
  138.  
  139.     begin
  140.         GetPort(oldPort);
  141.         printmgrsResFile := CurResFile;
  142.         if thePrRecHdl <> nil then
  143.             begin
  144.                 PrOpen;
  145.                 if (PrError = noErr) then
  146.                     begin
  147.                         if (PrError = noErr) then
  148.                             begin
  149.                                 if (PrStlDialog(thePrRecHdl)) then
  150.                 { Do any post-processing on the style dialog results you need to here }
  151.                                 else
  152.                                     PrSetError(iPrAbort);   {**  Cancel from the style dialog  **}
  153.                             end;
  154.                     end;
  155.                 PrintError := PrError;
  156.  
  157.                 PrClose;
  158.  
  159.                                             {**}
  160. {                                            You do not want to report any printing errors}
  161. {                                            until you}
  162. {                                            have fallen through the printing loop . This will make sure that ALL of the Print Manager 's open calls have their corresponding close calls, thereby}
  163. {                                            enabling the Print Manager to close properly and that all temporary memory allocations are released . * *}
  164.  
  165.                 if (PrintError <> noErr) and (PrintError <> iPrAbort) then
  166.  { PostPrintingErrors(PrintError); Need to add this }
  167.             end;
  168.  
  169.         UseResFile(printmgrsResFile);
  170.         SetPort(oldPort);
  171.         return true;
  172.     end; {PageSetup}
  173.  
  174. function Print (thePrRecHdl: THPrint): boolean;
  175.  
  176.     var
  177.         copies, firstPage, lastPage, numberOfCopies, pageNumber, printmgrsResFile, realNumberOfPagesInDoc: Integer;
  178.         PrintError: LongInt;
  179.         oldPort: GrafPtr;
  180.         thePrPort: TPPrPort;
  181. {theStatus: TPrStatus;}
  182.         PrintingStatusDialog: DialogPtr;
  183.         documentBounds: Rect;
  184.  
  185.     begin
  186.         GetPort(oldPort);
  187.         PrintingStatusDialog := nil;
  188.  
  189.     {**}
  190.         UnLoadTheWorld;
  191.  
  192.         if (MemError = noErr) and (thePrRecHdl <> nil) then
  193.             begin
  194.                 PrOpen;
  195.                 if (PrError = noErr) then
  196.                     begin
  197.  
  198. {                    Save the current resource file ( i . e . the printer driver's) so the driver will not lose its resources}
  199. {                    upon return from the pIdleProc.  }
  200.  
  201.                         printmgrsResFile := CurResFile;
  202.  
  203.                         if (PrError = noErr) then
  204.                             begin
  205.                                     {**}
  206. {                                    DetermineNumberOfPagesinDoc determines the number of pages contained in the document by comparing the size of the document}
  207. {                                    with rPage from the TPrInfo}
  208. {                                    record}
  209. {                                            ( IM II - 150 ) . It returns the number of pages required to print the document}
  210. {                                            for the currently selected printer . * *}
  211.  
  212.                                 documentPicture := GetPicture(256);
  213.                                 documentBounds := documentPicture^^.picFrame;
  214.                                 realNumberOfPagesinDoc := DetermineRealNumberOfPagesinDoc(documentBounds, thePrRecHdl);
  215.                                 ;
  216.  
  217.                                 if PrJobDialog(thePrRecHdl) then
  218.                                     begin
  219.  
  220. {                                                  Get the number of copies of the document that the user wants printed from iCopies of the TPrJob }
  221. {                                                    record}
  222. {                                                            ( IM II - 151 ) . * *}
  223.  
  224.                                         numberOfCopies := thePrRecHdl^^.prJob.iCopies;
  225.  
  226. {                                                            Get the first and last pages of the document that were requested to be printed by the user from iFstPage and iLastPage from the TPrJob}
  227. {                                                            record}
  228. {                                                                    ( IM II - 151 ) . * *}
  229.  
  230.                                         firstPage := thePrRecHdl^^.prJob.iFstPage;
  231.                                         lastPage := thePrRecHdl^^.prJob.iLstPage;
  232.  
  233. {                                                                    Print "}
  234. {                                                                    all "}
  235. {                                                                    pages in the print loop * *}
  236.  
  237.                                         thePrRecHdl^^.prJob.iFstPage := 1;
  238.                                         thePrRecHdl^^.prJob.iLstPage := 9999;
  239.  
  240. {                                                                    Determine the "}
  241. {                                                                    real "}
  242. {                                                                    number of pages contained in the document . Without this test , you would print 9999 pages . * *}
  243.  
  244.                                         if (realNumberOfPagesinDoc < lastPage) then
  245.                                             lastPage := realNumberOfPagesinDoc;
  246.  
  247.                                         PrintingStatusDialog := GetNewDialog(257, nil, POINTER(-1));
  248.  
  249.                                                                     {**}
  250. {                                                                    Print the number of copies of the document requested by the user from the Print Job Dialog . * *}
  251.  
  252.                                         for copies := 1 to numberOfCopies do
  253.                                             begin
  254.  
  255.                                                                             {**}
  256. {                                                                            Install a pointer to your pIdle proc in my print}
  257. {                                                                            record}
  258. {                                                                                    . * *}
  259.                                                 thePrRecHdl^^.prJob.pIdleProc := @MyPIdleProcedure;
  260.  
  261.                                                                                     {**}
  262. {                                                                                    Restore the resource}
  263. {                                                                                    file to the printer driver 's.}
  264. {                                                                                    * *}
  265.                                                 UseResFile(printmgrsResFile);
  266.  
  267.                                                 thePrPort := PrOpenDoc(thePrRecHdl, nil, nil);
  268.  
  269.                                                 SetPort(GrafPtr(thePrPort));
  270.  
  271.                                                 if (PrError = noErr) then
  272.                                                     begin
  273.                                                                                             {**}
  274. {                                                                                            Print the range of pages of the document requested by the user from the Print Job Dialog . * *}
  275.                                                         pageNumber := firstPage;
  276.                                                         while ((pageNumber <= lastPage) and (PrError = noErr)) do
  277.                                                             begin
  278.  
  279.                                                                 PrOpenPage(thePrPort, nil);
  280.  
  281.                                                                 if (PrError = noErr) then
  282.                                                                     begin
  283.                                                                                                             {**}
  284. {                                                                                                            rPage ( IM II - 150 ) is the printable area}
  285. {                                                                                                            for the currently selected printer . By passing the current enables your app to use the same routine to draw to the screen and the printer 's GrafPort.}
  286. {                                                                                                            * *}
  287.  
  288.                                                                         DrawStuff(thePrRecHdl^^.prInfo.rPage, GrafPtr(thePrPort), pageNumber, documentPicture);
  289.                                                                     end;
  290.                                                                 PrClosePage(thePrPort);
  291.                                                                 pageNumber := pageNumber + 1;
  292.                                                             end;  {**  End pagenumber loop  **}
  293.                                                     end;
  294.                                                 PrCloseDoc(thePrPort);
  295.                                             end; {**  End copies loop  **}
  296.  
  297.                                                                             {**}
  298. {                                                                            The printing job is being canceled by the request of the user from the Print Style Dialog or the Print Job Dialog . PrError will be}
  299. {                                                                            set to iPrAbort to tell the Print Manager to abort the current printing job . * *}
  300.                                     end
  301.                                 else
  302.                                     PrSetError(iPrAbort);   {**  Cancel from the job dialog  **}
  303.                             end;
  304.                     end;
  305.                 if (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) then
  306.                     PrPicFile(thePrRecHdl, nil, nil, nil, @theStatus);
  307.  
  308.                                             {**}
  309. {                                            Grab the printing error before you close the Print Manager and the error disappears . * *}
  310.  
  311.                 PrintError := PrError;
  312.  
  313.                 PrClose;
  314.  
  315.                                             {**}
  316. {                                            You do not want to report any printing errors}
  317. {                                            until you}
  318. {                                            have fallen through the printing loop . This will make sure that ALL of the Print Manager 's open calls have their corresponding close calls, thereby}
  319. {                                            enabling the Print Manager to close properly and that all temporary memory allocations are released . * *}
  320.  
  321.                 if (PrintError <> noErr) then
  322.  { PostPrintingErrors(PrintError); Need to add this }
  323.  
  324.             end;
  325.  
  326.         if (PrintingStatusDialog <> nil) then
  327.             DisposeDialog(PrintingStatusDialog);
  328.  
  329.         SetPort(oldPort);
  330.         return true;
  331.     end;  {**  print stuff  **}
  332. end.